/*
  Program: Mine Mayhem
  File:    mine.cc
  Date:    July, 1996 to February,   1997,    version 1.00
	   26 October to 3 December,	      version 2.00
	   8 December to 4 January,  2001,    version 2.10
	   15 January,			      version 2.11
	   18 September to 16 December, 2006, version 2.90

  Start everything rolling, then slow it down and stop it rolling.

  Freeware, Copyright 2006 Jason Hood.
*/

#include "mainmenu.h"
#include "minefld.h"
#include "board.h"
#include "inifile.h"
#include <stdlib.h>
#include <time.h>
#include "faces.h"
#include "digits.h"
#include "tiles.h"
#include "menuicon.h"
#include "timesicn.h"
#include <tws/sb.h>


MainMenuWindow* Main;

Minefield*    field;
SquareField*  squarefield;
RectHexField* recthexfield;
HexagonField* hexagonfield;
BoardWindow*  Board;

int  GameStyle, Game, Start, Finish, Counter, Hints;
int  hintsused;

bool isLogical, isMarks, isWrap, isTracked,
     isAutoMark, isAutoOpen, isAutoClear;

FONT *FixedFont, *FixedFontBold, *SysFont1, *SysFontBold1;
BYTE HighLightColour;

int  max_width, max_height, stath;

SOUND_SAMPLE *open_snd, *mark_snd, *win_snd, *die_snd;
bool isSound, SwapStereo, OpenSnd, MarkSnd, WinSnd, DieSnd;

bool use_normal_timing = false;


static void InitGraphics();
static void deInitGraphics();
static void InitOptions();
static void SaveOptions();


int main(int argc, char* argv[])
{
  if (argc > 1 && argv[1][0] == '-' &&
      (argv[1][1] == 't' || argv[1][1] == 'T'))
    use_normal_timing = true;

  srandom(time(NULL));

  ws.Init("mine.cfg");

  SysFont1 = SysFont;
  SysFontBold1 = SysFontBold;
  char* fixedfont, fixed[256];
  fixedfont = ws.GetConfigItem("fixed_font");
  if (fixedfont != NULL)
  {
    strcpy(fixed, fixedfont);
    strcat(fixed, ".fnt");
    FixedFont = LoadFont(fixed);
    if (FixedFont == NULL)
    {
      FixedFont = SysFont;
      FixedFontBold = SysFontBold;
    }
    else
    {
      strcpy(fixed, fixedfont);
      strcat(fixed, "b.fnt");
      FixedFontBold = LoadFont(fixed);
      if (FixedFontBold == NULL)
	FixedFontBold = SysFontBold;
    }
  }
  else
  {
    FixedFont = SysFont;
    FixedFontBold = SysFontBold;
  }

  fixedfont = ws.GetConfigItem("highlight_colour");
  HighLightColour = (fixedfont != NULL) ? atoi(fixedfont) : 25; // Blue

  //	   margin  time margin mines  shadow   layout & efficiency  mines+shadow
  stath = MAX(4 + DIGITH + 4 + DIGITH + 1,     2 * SysFont->height + DIGITH+2);

  //				     frame    margin outline
  max_width  = ws.GetDeskWidth() - (FWIDTH*2 + 4*2 +	2);

  max_height = ws.GetDeskHeight() -
  //	       <------------ menu ---------->	    margin+outline    frame
	       (SysFont->height+FWIDTH*2+4+4) - (stath + 5 + 5	   + FWIDTH*2);

  InitGraphics();

   squarefield = new SquareField;
  recthexfield = new RectHexField;
  hexagonfield = new HexagonField;

  InitOptions();
  switch (GameStyle)
  {
    default:
    case SQUARES:   field = squarefield;  break;
    case HEXAGONS:  field = recthexfield; break;
    case HEXAGONAL: field = hexagonfield; break;
  }

  Main = new MainMenuWindow;

  Board = new BoardWindow;

  if (isWrap)
  {
     squarefield->AdjustWrap();
    recthexfield->AdjustWrap();
    hexagonfield->AdjustWrap();
  }
  field->NewGame();

  if (isSound) ws.StartSound();
  ws.RunEvents();
  if (isSound) ws.StopSound();

  SaveOptions();

  delete Main; delete Board;
  delete squarefield; delete recthexfield; delete hexagonfield;

  deInitGraphics();

  if (FixedFont != SysFont)
    DeleteFont(FixedFont);
  if (FixedFontBold != SysFontBold)
    DeleteFont(FixedFontBold);

  return 0;
}


// Read the initialisation file and load times.
void InitOptions()
{
  IniFile ini("mine.ini");

   squarefield->ReadIni(ini);
  recthexfield->ReadIni(ini);
  hexagonfield->ReadIni(ini);

  GameStyle   = ini.GetInt( "Configuration", "Style",       SQUARES);
  Game	      = ini.GetInt( "Configuration", "Game",        CLEAR);
  Start       = ini.GetInt( "Configuration", "Start",       BLANK);
  Finish      = ini.GetInt( "Configuration", "Finish",      ALL_OPENED);
  Counter     = ini.GetInt( "Configuration", "Counter",     NORMAL);

  Hints       = ini.GetBool("Configuration", "Clues",       false);
  isLogical   = ini.GetBool("Configuration", "Logical",     true);
  isMarks     = ini.GetBool("Configuration", "Marks",       false);
  isWrap      = ini.GetBool("Configuration", "Wraparound",  false);
  isTracked   = ini.GetBool("Configuration", "Tracking",    false);
  isAutoMark  = ini.GetBool("Configuration", "AutoMark",    false);
  isAutoOpen  = ini.GetBool("Configuration", "AutoOpen",    false);
  isAutoClear = ini.GetBool("Configuration", "AutoClear",   false);

  isSound     = ini.GetBool("Sound",         "Sound",       false);
  SwapStereo  = ini.GetBool("Sound",         "SwapStereo",  false);
  OpenSnd     = ini.GetBool("Sound",         "OpenSound",   false);
  MarkSnd     = ini.GetBool("Sound",         "MarkSound",   false);
  WinSnd      = ini.GetBool("Sound",         "WinSound",    false);
  DieSnd      = ini.GetBool("Sound",         "DieSound",    false);

  if (open_snd == NULL) OpenSnd = false;
  if (mark_snd == NULL) MarkSnd = false;
  if (win_snd  == NULL) WinSnd	= false;
  if (die_snd  == NULL) DieSnd	= false;
}


// Write the initialisation file and save times.
void SaveOptions()
{
  IniFile ini("mine.ini");

   squarefield->WriteIni(ini);
  recthexfield->WriteIni(ini);
  hexagonfield->WriteIni(ini);

  ini.WriteInt(  "Configuration", "Style",       GameStyle);
  ini.WriteInt(  "Configuration", "Game",        Game);
  ini.WriteInt(  "Configuration", "Start",       Start);
  ini.WriteInt(  "Configuration", "Finish",      Finish);
  ini.WriteInt(  "Configuration", "Counter",     Counter);

  ini.WriteYesNo("Configuration", "Clues",       Hints);
  ini.WriteYesNo("Configuration", "Logical",     isLogical);
  ini.WriteYesNo("Configuration", "Marks",       isMarks);
  ini.WriteOnOff("Configuration", "Wraparound",  isWrap);
  ini.WriteYesNo("Configuration", "Tracking",    isTracked);
  ini.WriteOnOff("Configuration", "AutoMark",    isAutoMark);
  ini.WriteOnOff("Configuration", "AutoOpen",    isAutoOpen);
  ini.WriteOnOff("Configuration", "AutoClear",   isAutoClear);

  ini.WriteYesNo("Sound",         "Sound",       isSound);
  ini.WriteYesNo("Sound",         "SwapStereo",  SwapStereo);
  ini.WriteYesNo("Sound",         "OpenSound",   OpenSnd);
  ini.WriteYesNo("Sound",         "MarkSound",   MarkSnd);
  ini.WriteYesNo("Sound",         "WinSound",    WinSnd);
  ini.WriteYesNo("Sound",         "DieSound",    DieSnd);
}


// Create all the graphics and load the sound files.
void InitGraphics()
{
  const BYTE col[] = { 192,             //  0 - Grey
                       149,             //  1 - Dark grey
                       235,             //  2 - White
			20,		//  3 - Black
                       230,             //  4 - Yellow
		       146,		//  5 - Dark yellow
                       128,             //  6 - Dark red
                       200,             //  7 - Red
			25,		//  8 - Blue
			38,		//  9 - Green
			23,		// 10 - Dark blue
			41,		// 11 - Cyan
			 0,		// 12 - Transparent
			14,		// 13 - Mouse body
			18,		// 14 - Mouse left edge
			11,		// 15 - Mouse right edge
			 7,		// 16 - Mouse bottom
		       106,		// 17 - "faded" black
		       188,		// 18 - "faded" yellow
                     };
  int j;

  for (j = 0; j < MENUICONS; j++)
    MenuIcon[j] = BuildBuffer(MenuIconBuffer[j], MENUICONW, MENUICONH, col);

  for (j = 0; j < FACEICONS; j++)
    FaceIcon[j] = BuildBuffer(FaceIconBuffer[j], FACEICONW, FACEICONH, col);

  for (j = 0; j < DIGITS; j++)
  {
    Digit[j]	  = BuildBuffer(DigitBuffer[j], DIGITW, DIGITH, col);
    SmallDigit[j] = BuildBuffer(SmallDigitBuffer[j],
                                SMALLDIGITW, SMALLDIGITH, col);
  }
  for (j = 0; j < SQRTILES; j++)
    Square[j]  = BuildBuffer(SquareBuffer[j],  SQUAREW,  SQUAREH,  col);

  for (j = 0; j < HEXTILES; j++)
    Hexagon[j] = BuildBuffer(HexagonBuffer[j], HEXAGONW, HEXAGONH, col);

  for (j = 0; j < OTILES; j++)
    Overlay[j] = BuildBuffer(OverlayBuffer[j], OTILEW, OTILEH, col);

  int k = 0;
  for (j = 0; j < 3; ++j)
    TimesIconStart[j] = BuildBuffer(TimesIconBuffer[k++],
				    TIMESICONW, TIMESICONH, col);

  for (j = 0; j < 4; ++j)
    TimesIconFinish[j] = BuildBuffer(TimesIconBuffer[k++],
				     TIMESICONW, TIMESICONH, col);

  for (j = 0; j < 3; ++j)
    TimesIconCounter[j] = BuildBuffer(TimesIconBuffer[k++],
				      TIMESICONW, TIMESICONH, col);

  for (int i = 0; i < 2; ++i)
    for (j = 0; j < 2; ++j)
      TimesIconGeneral[i][j] = BuildBuffer(TimesIconBuffer[k++],
					   TIMESICONW, TIMESICONH, col);

  for (j = 0; j < 2; ++j)
    TimesIconClear[j] = BuildBuffer(TimesIconBuffer[k++],
				    TIMESICONW, TIMESICONH, col);

  TimesIconWrap = BuildBuffer(TimesIconBuffer[k++], TIMESICONW,TIMESICONH, col);

  open_snd = LoadWaveFile("sound/open.wav");
  mark_snd = LoadWaveFile("sound/mark.wav");
  win_snd  = LoadWaveFile("sound/win.wav");
  die_snd  = LoadWaveFile("sound/die.wav");
}


// Destroy all the graphics and the samples.
void deInitGraphics()
{
  int j;
  for (j = 0; j < OTILES;   j++) DeleteBuffer(Overlay[j]);
  for (j = 0; j < HEXTILES; j++) DeleteBuffer(Hexagon[j]);
  for (j = 0; j < SQRTILES; j++) DeleteBuffer(Square[j]);
  for (j = 0; j < DIGITS; j++)
  {
    DeleteBuffer(SmallDigit[j]);
    DeleteBuffer(Digit[j]);
  }
  for (j = 0; j < FACEICONS; j++) DeleteBuffer(FaceIcon[j]);
  for (j = 0; j < MENUICONS; j++) DeleteBuffer(MenuIcon[j]);
  for (j = 0; j < 3; ++j)	  DeleteBuffer(TimesIconStart[j]);
  for (j = 0; j < 4; ++j)	  DeleteBuffer(TimesIconFinish[j]);
  for (j = 0; j < 3; ++j)	  DeleteBuffer(TimesIconCounter[j]);
  for (j = 0; j < 2; ++j)
    for (int k = 0; k < 2; ++k)   DeleteBuffer(TimesIconGeneral[j][k]);
  for (j = 0; j < 2; ++j)	  DeleteBuffer(TimesIconClear[j]);
  DeleteBuffer(TimesIconWrap);

  if (open_snd) DeleteSample(open_snd);
  if (mark_snd) DeleteSample(mark_snd);
  if (win_snd)	DeleteSample(win_snd);
  if (die_snd)	DeleteSample(die_snd);
}
